package com.test.jogl;

import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCanvas;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLJPanel;

import com.sun.opengl.util.Animator;

//import static 

public class City implements GLEventListener, MouseListener, MouseMotionListener {

//private static int NB_CLICK = 0;
   
   private static final float EDGE_SIZE = 5.0F;
   
   private float view_rotx = 0.0f, view_roty = 0.0f, view_rotz = 0.0f;
   

   /**
    * @param args
    */
   public static void main(String[] args) {
      Frame frame = new Frame("Settlers of Catan");
      GLCanvas canvas = new GLCanvas();

      canvas.addGLEventListener(new City());
      frame.add(canvas);
      frame.setSize(600, 600);
      final Animator animator = new Animator(canvas);
      frame.addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
            // Run this on another thread than the AWT event queue to
            // make sure the call to Animator.stop() completes before
            // exiting
            new Thread(new Runnable() {
               public void run() {
                  animator.stop();
                  System.exit(0);
               }
            }).start();
         }
      });
      frame.setVisible(true);
      animator.start();
   }

   private int prevMouseX, prevMouseY;
   private int id; 

   private boolean mouseRButtonDown = false;

   public void init(GLAutoDrawable drawable) {
      // Use debug pipeline
      // drawable.setGL(new DebugGL(drawable.getGL()));

      
      GL gl = drawable.getGL();

      System.err.println("INIT GL IS: " + gl.getClass().getName());

      System.err.println("Chosen GLCapabilities: "
            + drawable.getChosenGLCapabilities());

      gl.setSwapInterval(1);

      float pos[] = { 5.0f, 5.0f, 10.0f, 0.0f };
      float red[] = { 0.8f, 0.1f, 0.0f, 1.0f };
      float green[] = { 0.0f, 0.9f, 0.2f, 1.0f };
      float blue[] = { 0.2f, 0.2f, 1.0f, 1.0f };

      gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, pos, 0);
      gl.glEnable(GL.GL_CULL_FACE);
      gl.glEnable(GL.GL_LIGHTING);
      gl.glEnable(GL.GL_LIGHT0);
      gl.glEnable(GL.GL_DEPTH_TEST);
      
      id = gl.glGenLists(1);
      gl.glNewList(1, GL.GL_COMPILE);
      gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_SHININESS, blue, 1);
      gl.glColorMaterial(GL.GL_FRONT_AND_BACK, GL.GL_SHININESS);
      city(gl, 0.0F, 0.0F, EDGE_SIZE);
      gl.glEndList();
      /*
      int c = 0;
      listHex = new ArrayList<Integer>();
      for (Point2D.Float currentPos : list2D) {
         currentPos = list2D.get(c);
         System.out.println("Case #" + (c+1));
         listHex.add(gl.glGenLists(1));
         gl.glNewList(listHex.get(c), GL.GL_COMPILE);
         if(c < (MAP_SIZE - 2) * 6) {
            gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT_AND_DIFFUSE, blue, 0);
         }
         else {
            gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT_AND_DIFFUSE, nextColor() ? red : green, 0);
         }
         gl.glColorMaterial(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT_AND_DIFFUSE);
         
         hexagon(gl, currentPos.x * EDGE_SIZE, currentPos.y * EDGE_SIZE, EDGE_SIZE);
         gl.glEndList();
         c++;
      }*/
      
      gl.glEnable(GL.GL_NORMALIZE);

      drawable.addMouseListener(this);
      drawable.addMouseMotionListener(this);
   }

   public void display(GLAutoDrawable drawable) {
      GL gl = drawable.getGL();
      if ((drawable instanceof GLJPanel) && !((GLJPanel) drawable).isOpaque()
            && ((GLJPanel) drawable).shouldPreserveColorBufferIfTranslucent()) {
         gl.glClear(GL.GL_DEPTH_BUFFER_BIT);
      } else {
         gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
      }

      gl.glPushMatrix();
      gl.glRotatef(view_rotx, 1.0f, 0.0f, 0.0f);
      gl.glRotatef(view_roty, 0.0f, 1.0f, 0.0f);
      gl.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f);

      gl.glPushMatrix();
      gl.glTranslatef(-3.0f, 2.0f, 0.0f);
      // gl.glRotatef(angle, 0.0f, 0.0f, 1.0f);
      
      gl.glCallList(id);

      gl.glPopMatrix();
   }

   public void displayChanged(GLAutoDrawable drawable, boolean modeChanged,
         boolean deviceChanged) {
   }

   public static void city(GL gl, float initX, float initY, float edge) {

      float z = 0.0F;
      float halfEdge = 0.5F * edge;
      float quarterEdge = 0.25F * edge;
      
      gl.glShadeModel(GL.GL_FLAT);
      gl.glNormal3f(0.0f, 0.0f, 1.0f);

      // 1er mur: Face
      gl.glBegin(GL.GL_POLYGON);
      gl.glShadeModel(GL.GL_FLAT);
      gl.glVertex3f(initX + halfEdge, initY - halfEdge, z + quarterEdge);
      gl.glVertex3f(initX - halfEdge, initY - halfEdge, z + quarterEdge);
      gl.glVertex3f(initX - halfEdge, initY + halfEdge, z + quarterEdge);
      gl.glVertex3f(initX + halfEdge, initY + halfEdge, z + quarterEdge);
      gl.glEnd();

      // 2er mur: Gauche
      gl.glBegin(GL.GL_POLYGON);
      gl.glShadeModel(GL.GL_FLAT);
      gl.glVertex3f(initX - halfEdge, initY - halfEdge, z + quarterEdge);
      gl.glVertex3f(initX - halfEdge, initY - halfEdge, z - quarterEdge);
      gl.glVertex3f(initX - halfEdge, initY + halfEdge, z - quarterEdge);
      gl.glVertex3f(initX - halfEdge, initY + halfEdge, z + quarterEdge);
      gl.glEnd();
      
      // 3e mur: Arriere
      gl.glBegin(GL.GL_POLYGON);
      gl.glShadeModel(GL.GL_FLAT);
      gl.glVertex3f(initX + halfEdge, initY - halfEdge, z - quarterEdge);
      gl.glVertex3f(initX - halfEdge, initY - halfEdge, z - quarterEdge);
      gl.glVertex3f(initX - halfEdge, initY + halfEdge, z - quarterEdge);
      gl.glVertex3f(initX + halfEdge, initY + halfEdge, z - quarterEdge);
      gl.glEnd();

      // 2er mur: Droite
      gl.glBegin(GL.GL_POLYGON);
      gl.glShadeModel(GL.GL_FLAT);
      gl.glVertex3f(initX + halfEdge, initY - halfEdge, z + quarterEdge);
      gl.glVertex3f(initX + halfEdge, initY - halfEdge, z - quarterEdge);
      gl.glVertex3f(initX + halfEdge, initY + halfEdge, z - quarterEdge);
      gl.glVertex3f(initX + halfEdge, initY + halfEdge, z + quarterEdge);
      gl.glEnd();
      
      // Toit avant
      gl.glBegin(GL.GL_POLYGON);
      gl.glShadeModel(GL.GL_FLAT);
      gl.glVertex3f(initX - halfEdge, initY + halfEdge, z + quarterEdge);
      gl.glVertex3f(initX + halfEdge, initY + halfEdge, z + quarterEdge);
      gl.glVertex3f(initX + halfEdge, initY + edge,     z);
      gl.glVertex3f(initX - halfEdge, initY + edge,     z);
      gl.glEnd();
      
      // Toit arriere
      gl.glBegin(GL.GL_POLYGON);
      gl.glShadeModel(GL.GL_FLAT);
      gl.glVertex3f(initX - halfEdge, initY + halfEdge, z - quarterEdge);
      gl.glVertex3f(initX + halfEdge, initY + halfEdge, z - quarterEdge);
      gl.glVertex3f(initX + halfEdge, initY + edge,     z);
      gl.glVertex3f(initX - halfEdge, initY + edge,     z);
      gl.glEnd();
      
      // Toit de droite
      gl.glBegin(GL.GL_POLYGON);
      gl.glShadeModel(GL.GL_FLAT);
      gl.glVertex3f(initX + halfEdge, initY + halfEdge, z - quarterEdge);
      gl.glVertex3f(initX + halfEdge, initY + halfEdge, z + quarterEdge);
      gl.glVertex3f(initX + halfEdge, initY + edge,     z);
      gl.glEnd();
      
   // Toit de gauche
      gl.glBegin(GL.GL_POLYGON);
      gl.glShadeModel(GL.GL_FLAT);
      gl.glVertex3f(initX - halfEdge, initY + halfEdge, z - quarterEdge);
      gl.glVertex3f(initX - halfEdge, initY + halfEdge, z + quarterEdge);
      gl.glVertex3f(initX - halfEdge, initY + edge,     z);
      gl.glEnd();
   }

   
   // Methods required for the implementation of MouseListener
   public void mouseEntered(MouseEvent e) {
   }

   public void mouseExited(MouseEvent e) {
   }

   public void mousePressed(MouseEvent e) {
      prevMouseX = e.getX();
      prevMouseY = e.getY();
      if ((e.getModifiers() & e.BUTTON3_MASK) != 0) {
         mouseRButtonDown = true;
      }
   }

   public void mouseReleased(MouseEvent e) {
      if ((e.getModifiers() & e.BUTTON3_MASK) != 0) {
         mouseRButtonDown = false;
      }
   }

   public void mouseClicked(MouseEvent e) {
      //NB_CLICK++;
   }

   // Methods required for the implementation of MouseMotionListener
   public void mouseDragged(MouseEvent e) {
      int x = e.getX();
      int y = e.getY();
      Dimension size = e.getComponent().getSize();

      float thetaY = 360.0f * ((float) (x - prevMouseX) / (float) size.width);
      float thetaX = 360.0f * ((float) (prevMouseY - y) / (float) size.height);

      prevMouseX = x;
      prevMouseY = y;

      view_rotx += thetaX;
      view_roty += thetaY;
   }

   public void mouseMoved(MouseEvent e) {
   }

   public void reshape(GLAutoDrawable drawable, int x, int y, int width,
         int height) {
      GL gl = drawable.getGL();

      float h = (float) height / (float) width;

      gl.glMatrixMode(GL.GL_PROJECTION);

      System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
      System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
      System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
      gl.glLoadIdentity();
      gl.glFrustum(-1.0f, 1.0f, -h, h, 5.0f, 60.0f);
      gl.glMatrixMode(GL.GL_MODELVIEW);
      gl.glLoadIdentity();
      gl.glTranslatef(0.0f, 0.0f, -40.0f);
   }

}
